var fVertexShaderSource = `#version 300 es
in vec4 a_position;
in vec4 a_color;
uniform mat4 u_matrix;
out vec4 v_color;
void main() {
  gl_Position = u_matrix * a_position;
  v_color = a_color;
}
`;

var fFragmentShaderSource = `#version 300 es
precision highp float;
in vec4 v_color;
out vec4 outColor;
void main() {
  outColor = v_color;
}
`;

var textVertexShaderSource = `#version 300 es
in vec4 a_position;
in vec2 a_texcoord;
uniform mat4 u_matrix;
out vec2 v_texcoord;
void main() {
  gl_Position = u_matrix * a_position;
  v_texcoord = a_texcoord;
}
`;

var textFragmentShaderSource = `#version 300 es
precision highp float;
in vec2 v_texcoord;
uniform sampler2D u_texture;
out vec4 outColor;
void main() {
   outColor = texture(u_texture, v_texcoord);
}
`;

var textCtx = document.createElement("canvas").getContext("2d");
function makeTextCanvas(text, width, height) {
  textCtx.canvas.width  = width;
  textCtx.canvas.height = height;
  textCtx.font = "20px monospace";
  textCtx.textAlign = "center";
  textCtx.textBaseline = "middle";
  textCtx.fillStyle = "black";
  textCtx.clearRect(0, 0, textCtx.canvas.width, textCtx.canvas.height);
  textCtx.fillText(text, width / 2, height / 2);
  return textCtx.canvas;
}

function main() {
  var canvas = document.querySelector("#canvas");
  var gl = canvas.getContext("webgl2");

  gl.enable(gl.BLEND);
  gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);

  twgl.setAttributePrefix("a_");
  var fProgramInfo = twgl.createProgramInfo(gl, [fVertexShaderSource, fFragmentShaderSource]);
  var textProgramInfo = twgl.createProgramInfo(gl, [textVertexShaderSource, textFragmentShaderSource]);
  var fBufferInfo = twgl.primitives.create3DFBufferInfo(gl);
  var fVAO = twgl.createVAOFromBufferInfo(gl, fProgramInfo, fBufferInfo);
  var textBufferInfo = twgl.primitives.createXYQuadBufferInfo(gl, 1);
  var textVAO = twgl.createVAOFromBufferInfo(gl, textProgramInfo, textBufferInfo);
  var textCanvas = makeTextCanvas("Hello!", 100, 26);
  var textWidth  = textCanvas.width;
  var textHeight = textCanvas.height;
  var textTex = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, textTex);
  gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textCanvas);
  gl.generateMipmap(gl.TEXTURE_2D);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

  var fUniforms = {
    u_matrix: m4.identity(),
  };

  var textUniforms = {
    u_matrix: m4.identity(),
    u_texture: textTex,
  };

  function degToRad(d) {
    return d * Math.PI / 180;
  }

  var translation = [0, 0, 0];
  var rotation = [degToRad(190), degToRad(0), degToRad(0)];
  var scale = [1, 1, 1];
  var fieldOfViewRadians = degToRad(60);
  var rotationSpeed = 1.2;

  var then = 0;

  requestAnimationFrame(drawScene);

  function drawScene(time) {
    var now = time * 0.001;
    var deltaTime = now - then;
    then = now;
    twgl.resizeCanvasToDisplaySize(gl.canvas);
    rotation[1] += rotationSpeed * deltaTime;
    gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
    gl.clearColor(0, 0, 0, 0);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    gl.enable(gl.DEPTH_TEST);
    gl.enable(gl.CULL_FACE);
    var aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
    var projectionMatrix = m4.perspective(fieldOfViewRadians, aspect, 1, 2000);
    var cameraRadius = 360;
    var cameraPosition = [Math.cos(now) * cameraRadius, 0, Math.sin(now) * cameraRadius];
    var target = [0, 0, 0];
    var up = [0, 1, 0];
    var cameraMatrix = m4.lookAt(cameraPosition, target, up);
    var viewMatrix = m4.inverse(cameraMatrix);

    var fViewMatrix = m4.translate(viewMatrix, translation[0], translation[1], translation[2]);
    fViewMatrix = m4.xRotate(fViewMatrix, rotation[0]);
    fViewMatrix = m4.yRotate(fViewMatrix, rotation[1]);
    fViewMatrix = m4.zRotate(fViewMatrix, rotation[2] + now );
    fViewMatrix = m4.scale(fViewMatrix, scale[0], scale[1], scale[2]);
    fViewMatrix = m4.translate(fViewMatrix, -50, -75, 0);

    gl.useProgram(fProgramInfo.program);
    gl.bindVertexArray(fVAO);

    fUniforms.u_matrix = m4.multiply(projectionMatrix, fViewMatrix);
    twgl.setUniforms(fProgramInfo, fUniforms);
    twgl.drawBufferInfo(gl, fBufferInfo);

    // var textMatrix = m4.translate(projectionMatrix, fViewMatrix[12], fViewMatrix[13], fViewMatrix[14]);
    var textMatrix2 = m4.translate(projectionMatrix, fViewMatrix[12], fViewMatrix[13], fViewMatrix[14]);

    var textMMatrix = m4.translate(m4.identity(), fViewMatrix[12], fViewMatrix[13], fViewMatrix[14]);
    var textMatrix = m4.multiply(projectionMatrix, textMMatrix);

    textMatrix = m4.scale(textMatrix, textWidth, textHeight, 1);
    gl.useProgram(textProgramInfo.program);
    gl.bindVertexArray(textVAO);
    m4.copy(textMatrix, textUniforms.u_matrix);
    twgl.setUniforms(textProgramInfo, textUniforms);
    twgl.drawBufferInfo(gl, textBufferInfo);

    requestAnimationFrame(drawScene);
  }
}

main();
